package com.jinwei.qunguanjia.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.jinwei.qunguanjia.system.dao.SysRoleDAO;
import com.jinwei.qunguanjia.system.dao.SysRoleDeptDAO;
import com.jinwei.qunguanjia.system.dao.SysRoleMenuDAO;
import com.jinwei.qunguanjia.system.dao.SysUserRoleDAO;
import com.jinwei.qunguanjia.system.dto.SysRoleDTO;
import com.jinwei.qunguanjia.system.po.SysRoleDeptPO;
import com.jinwei.qunguanjia.system.po.SysRoleMenuPO;
import com.jinwei.qunguanjia.system.po.SysRolePO;
import com.jinwei.qunguanjia.system.po.SysUserRolePO;
import com.jinwei.qunguanjia.system.utils.SecurityUtils;
import com.jinwei.qunguanjia.common.constant.UserConstants;
import com.jinwei.qunguanjia.common.core.domain.model.Condition;
import com.jinwei.qunguanjia.common.core.page.PageDataInfo;
import com.jinwei.qunguanjia.common.enums.HttpResponseEnum;
import com.jinwei.qunguanjia.common.exception.GlobalExceptionHelper;
import com.jinwei.qunguanjia.common.utils.*;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * 角色 业务层处理
 *
 * @author ruoyi
 */
@Service("sysRoleService")
public class SysRoleServiceImpl implements SysRoleService {

    @Resource
    private SysRoleDAO sysRoleDAO;

    @Resource
    private SysRoleMenuDAO sysRoleMenuDAO;

    @Resource
    private SysRoleDeptDAO sysRoleDeptDAO;

    @Resource
    private SysUserRoleDAO sysUserRoleDAO;

    @Override
    @Transactional
    public void save(SysRoleDTO sysRoleDTO) {
        // 新增角色信息
        String id = IdUtils.getWorkerId();
        sysRoleDTO.setRoleId(id);
        SysRolePO sysRolePO = new SysRolePO();
        BeanUtils.copyProperties(sysRoleDTO, sysRolePO);
        sysRoleDAO.insert(sysRolePO);
        saveRoleMenu(sysRoleDTO);
    }

    @Override
    public void remove(List<String> ids) {
        for (String roleId : ids) {
            checkRoleAllowed(roleId);
            checkRoleDataScope(roleId);
            SysRoleDTO role = get(roleId);
            if (countUserRoleByRoleId(roleId) > 0) {
                throw GlobalExceptionHelper.localServiceException(HttpResponseEnum.INTERNAL_SERVER_ERROR.getCode(),"{} 已分配,不能删除", role.getRoleName());
            }
        }
        // 删除角色与菜单关联
        LambdaQueryWrapper<SysRoleMenuPO> lambdaWrapper = new LambdaQueryWrapper<>();
        lambdaWrapper.in(SysRoleMenuPO::getRoleId, ids);
        sysRoleMenuDAO.delete(lambdaWrapper);
        // 删除角色与部门关联
        LambdaQueryWrapper<SysRoleDeptPO> lambdaWrapper1 = new LambdaQueryWrapper<>();
        lambdaWrapper1.in(SysRoleDeptPO::getRoleId, ids);
        sysRoleDeptDAO.delete(lambdaWrapper1);
        LambdaQueryWrapper<SysRolePO> lambdaWrapper2 = new LambdaQueryWrapper<>();
        lambdaWrapper2.in(SysRolePO::getRoleId, ids);
        sysRoleDAO.delete(lambdaWrapper2);
    }

    @Override
    @Transactional
    public Integer update(SysRoleDTO sysRoleDTO) {
        // 修改角色信息
        SysRolePO sysRolePO = new SysRolePO();
        BeanUtils.copyProperties(sysRoleDTO, sysRolePO);
        sysRoleDAO.updateById(sysRolePO);
        // 删除角色与菜单关联
        LambdaQueryWrapper<SysRoleMenuPO> lambdaWrapper = new LambdaQueryWrapper<>();
        lambdaWrapper.eq(SysRoleMenuPO::getRoleId, sysRoleDTO.getRoleId());
        sysRoleMenuDAO.delete(lambdaWrapper);
        return saveRoleMenu(sysRoleDTO);
    }
    public void updateRoleStatus(SysRoleDTO sysRoleDTO) {
        // 修改角色信息
        SysRolePO sysRolePO = new SysRolePO();
        BeanUtils.copyProperties(sysRoleDTO, sysRolePO);
        sysRoleDAO.updateById(sysRolePO);
    }

    @Override
    public SysRoleDTO get(String id) {
        SysRolePO sysRolePO = sysRoleDAO.selectById(id);
        SysRoleDTO sysRoleDTO = new SysRoleDTO();
        BeanUtils.copyProperties(sysRolePO, sysRoleDTO);
        return sysRoleDTO;
    }

    @Override
    public SysRoleDTO get(SysRoleDTO sysRoleDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(sysRoleDTO);
        // 拼接查询条件
        QueryWrapper<SysRolePO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        SysRolePO sysRolePO = sysRoleDAO.selectOne(queryWrapper);
        if (null == sysRolePO) {
            return null;
        }
        BeanUtils.copyProperties(sysRolePO, sysRoleDTO);
        return sysRoleDTO;
    }

    @Override
    public List<SysRoleDTO> list(SysRoleDTO sysRoleDTO) throws IllegalAccessException {
        // 添加查询条件
        List<Condition> conditionList = ConditionUtils.add(sysRoleDTO);
        // 拼接查询条件
        QueryWrapper<SysRolePO> queryWrapper = SearchUtils.parseWhereSql(conditionList);
        return JsonUtils.copyList(sysRoleDAO.selectList(queryWrapper), SysRoleDTO.class);
    }

    @Override
    public PageDataInfo<SysRoleDTO> listPage(SysRoleDTO sysRoleDTO) {
        List<SysRoleDTO> list = sysRoleDAO.listRole(sysRoleDTO);
        PageInfo<SysRoleDTO> pageInfo = new PageInfo<>(list);
        PageDataInfo<SysRoleDTO> pageDataInfo = new PageDataInfo<>();
        pageDataInfo.setData(list);
        pageDataInfo.setTotal(pageInfo.getTotal());
        return pageDataInfo;
    }

    @Override
    public Set<String> listRolePermissionByUserId(String userId) {
        List<SysRoleDTO> perms = sysRoleDAO.listRoleByUserId(userId);
        Set<String> permsSet = new HashSet<>();
        for (SysRoleDTO perm : perms) {
            if (StringUtils.isNotNull(perm)) {
                permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
            }
        }
        return permsSet;
    }

    @Override
    public String checkRoleNameUnique(SysRoleDTO sysRoleDTO) throws IllegalAccessException {
        String roleId = StringUtils.isNull(sysRoleDTO.getRoleId()) ? "-1" : sysRoleDTO.getRoleId();
        SysRoleDTO info = get(SysRoleDTO.builder().roleName(sysRoleDTO.getRoleName()).build());
        if (StringUtils.isNotNull(info) && !info.getRoleId().equals(roleId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public String checkRoleKeyUnique(SysRoleDTO sysRoleDTO) throws IllegalAccessException {
        String roleId = StringUtils.isNull(sysRoleDTO.getRoleId()) ? "-1" : sysRoleDTO.getRoleId();
        SysRoleDTO info = get(SysRoleDTO.builder().roleKey(sysRoleDTO.getRoleKey()).build());
        if (StringUtils.isNotNull(info) && !info.getRoleId().equals(roleId)) {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public void checkRoleAllowed(String roleId) {
        if (StringUtils.isNotNull(roleId) && SecurityUtils.isRoleAdmin(roleId)) {
            throw GlobalExceptionHelper.localServiceException("不允许操作超级管理员角色");
        }
    }

    @Override
    public void checkRoleDataScope(String roleId) {
        if (!SecurityUtils.isAdmin()) {
            SysRoleDTO sysRoleDTO = new SysRoleDTO();
            sysRoleDTO.setRoleId(roleId);
            List<SysRoleDTO> roles = listPage(sysRoleDTO).getData();
            if (StringUtils.isEmpty(roles)) {
                throw GlobalExceptionHelper.localServiceException("没有权限访问角色数据");
            }
        }
    }

    @Override
    @Transactional
    public void updateDataScope(SysRoleDTO sysRoleDTO) {
        // 修改角色信息
        SysRolePO sysRolePO = new SysRolePO();
        BeanUtils.copyProperties(sysRoleDTO, sysRolePO);
        sysRoleDAO.updateById(sysRolePO);
        // 删除角色与部门关联
        LambdaQueryWrapper<SysRoleDeptPO> lambdaWrapper = new LambdaQueryWrapper<>();
        lambdaWrapper.eq(SysRoleDeptPO::getRoleId, sysRoleDTO.getRoleId());
        sysRoleDeptDAO.delete(lambdaWrapper);
        // 新增角色和部门信息（数据权限）
        saveRoleDept(sysRoleDTO);
    }

    @Override
    public void removeAuthUser(String roleId, String userId) {
        LambdaQueryWrapper<SysUserRolePO> lambdaWrapper = new LambdaQueryWrapper<>();
        lambdaWrapper.eq(SysUserRolePO::getRoleId, roleId);
        lambdaWrapper.eq(SysUserRolePO::getUserId, userId);
        sysUserRoleDAO.delete(lambdaWrapper);
    }

    @Override
    public void removeAuthUsers(String roleId, String[] userIds) {
        LambdaQueryWrapper<SysUserRolePO> lambdaWrapper = new LambdaQueryWrapper<>();
        lambdaWrapper.eq(SysUserRolePO::getRoleId, roleId);
        lambdaWrapper.in(SysUserRolePO::getUserId, Arrays.asList(userIds));
        sysUserRoleDAO.delete(lambdaWrapper);
    }

    @Override
    public void saveAuthUsers(String roleId, String[] userIds) {
        // 新增用户与角色管理
        List<SysUserRolePO> list = new ArrayList<>();
        for (String userId : userIds) {
            SysUserRolePO ur = new SysUserRolePO();
            ur.setUserId(userId);
            ur.setRoleId(roleId);
            list.add(ur);
        }
        sysUserRoleDAO.saveBatch(list);
    }

    /**
     * 新增角色菜单信息
     *
     * @param role 角色对象
     */
    private int saveRoleMenu(SysRoleDTO role)
    {
        int rows = 0;
        // 新增用户与角色管理
        List<SysRoleMenuPO> list = new ArrayList<>();
        for (String menuId : role.getMenuIds()) {
            SysRoleMenuPO rm = new SysRoleMenuPO();
            rm.setRoleId(role.getRoleId());
            rm.setMenuId(menuId);
            list.add(rm);
        }
        if (list.size() > 0) {
            rows = sysRoleMenuDAO.saveBatch(list);
        }
        return rows;
    }
    /**
     * 新增角色部门信息(数据权限)
     *
     * @param role 角色对象
     */
    private void saveRoleDept(SysRoleDTO role) {
        // 新增角色与部门（数据权限）管理
        List<SysRoleDeptPO> list = new ArrayList<>();
        for (String deptId : role.getDeptIds()) {
            SysRoleDeptPO rd = new SysRoleDeptPO();
            rd.setRoleId(role.getRoleId());
            rd.setDeptId(deptId);
            list.add(rd);
        }
        if (list.size() > 0) {
           sysRoleDeptDAO.saveBatch(list);
        }
    }

    private Long countUserRoleByRoleId(String roleId) {
        LambdaQueryWrapper<SysUserRolePO> lambdaWrapper = new LambdaQueryWrapper<>();
        lambdaWrapper.eq(SysUserRolePO::getRoleId, roleId);
        return sysUserRoleDAO.selectCount(lambdaWrapper);
    }
}
